<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      ////T1
        var F;
        var f;
        var F = function () {};
        Object.prototype.a = function () {
          console.log("a");
        };
        Function.prototype.b = function () {
          console.log("b");
        };
        var f = new F();
        f.a();   //a    
        //实例f 的函数是 F，F函数里面没有a，从实例出发，F函数的显示原型的__proto__等于Object.prototype

        // f.b();   //报错  
        //实例f 的构造函数是F， F里面没有b，因为是从实例出发，函数的prototype的proto等于Object.prototype，object的prototype里没有，Obj.prototype是 唯一一个没有__proto__的对象数据类型，会是null，所以会报错

        F.a();   //a  
        //F是函数，从函数里面找a，F函数没有，函数都是Function的实例，所以去到Function的prototype里去找，里面也没有a，Function的prototype的proto等于Object的prototype，所以打印a

        F.b();   //b  
        //F是函数，从里面找b，F函数没有，函数都是Function的实例，所以去到Function的prototype里面找，里面有b，所以打印b


      //   //T2
        var A;
        var b;
        var c;

        var A = function () {};  //A是函数

        A.prototype.n = 1;

        var b = new A();  //b 是A的实例

        A.prototype = {
          n: 2,
          m: 3,
        };

        var c = new A();  //c 是A的实例

        console.log(b.n); // 1   
        // b是A函数的实例，A函数的prototype里有n的值，所以打印1

        console.log(b.m);  //undefined  
        // b是A函数的实例，它实例化的时候A函数的prototype里还没有m。A.prototype是一个对象，打印里面没有的值，都是返回undefined

        console.log(c.n); //2  
        // c是A函数的实例，它实例化的时候，A函数的prototype里有n，所以打印2

        console.log(c.m);  //3  
        // c是A函数的实例，它实例化的时候，A函数的prototype里有m，所以打印3



      //   //T3
        var foo = {},    //foo是一个空对象
          F = function () {};  //F是一个函数

        Object.prototype.a = "value a";
        Function.prototype.b = "value b";

        console.log(foo.a);  //value a  
        //单纯的对象，都是Object的实例,所以foo对象里没有a，可以到Object的prototype里找，Object里面有，所以打印value a

        console.log(foo.b);  //undefined 
        //单纯的对象，都是Object的实例,所以foo对象里没有b，可以到Object的prototype里找，Object里面没有，可以到Object的prototype的proto里找，但是Object.prototype是没有__proto__的，打印一个对象里面没有的值，返回undefined

        console.log(F.a);  //value a  
        //F是函数，打印F函数里面的a，F函数里面没有a，但是函数都是Function的实例，所以可以到Function.prototype里找，Function.prototype里面没有。Function.prototype.__proto__等于Object的prototype，所以打印value a 

        console.log(F.b);  //value b
        //F是函数，打印F函数里面的a，F函数里面没有a，但是函数都是Function的实例，所以可以到Function.prototype里找，Function.prototype里有,所以打印value b 


      //   //T4

        function A() {}   //A函数

        function B(a) {   //B函数
          this.a = a;   //this指向 ---谁调用B函数 就指向谁，谁是该函数的实例，就指向该实例
        }

        function C(a) {   //C函数
          if (a) {
            this.a = a;   //this指向 ---谁调用C函数 就指向谁，谁是该函数的实例，就指向该实例
          }
        }
        
        A.prototype.a = 1;
        B.prototype.a = 1;
        C.prototype.a = 1;

        console.log(new A().a);  //1     打印A函数实例的a (实例没有命名，因为没有使用变量来接)
        console.log(new B().a);   //undefined     打印B函数实例的a ，B函数自己有形参a，所以不用到原型里面找。但是形参a没有传实参，没赋值，所以是未定义undefined
        console.log(new C(2).a);  //2   打印C函数实例的a ，实例有传实参2到C函数，C函数的a被赋值为2，所以打印2

    </script>
  </body>
</html>
